{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "d1ae70e1-1354-4aa6-9dc4-73d3c7b016c5",
   "metadata": {},
   "source": [
    "# Window and custom features\n",
    "\n",
    "When forecasting time series data, it may be useful to consider additional characteristics of the time series beyond just the lagged values. For example, the moving average of the previous *n* values may help to capture the trend in the series. The `window_features` argument allows the inclusion of additional predictors created with the previous values of the series."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3a00885b",
   "metadata": {},
   "source": [
    "<div class=\"admonition note\" name=\"html-admonition\" style=\"background: rgba(255,145,0,.1); padding-top: 0px; padding-bottom: 6px; border-radius: 8px; border-left: 8px solid #ff9100; border-color: #ff9100; padding-left: 10px; padding-right: 10px\">\n",
    "\n",
    "<p class=\"title\">\n",
    "    <i style=\"font-size: 18px; color:#ff9100; border-color: #ff1744;\"></i>\n",
    "    <b style=\"color: #ff9100;\"> <span style=\"color: #ff9100;\">&#9888;</span> Warning</b>\n",
    "</p>\n",
    "\n",
    "<p>\n",
    "  This section focuses on window features and other user-defined features derived from past values of the time series being modelled. These features are different from exogenous variables. Exogenous variables are external to the time series and are added to the model as additional predictors. See the \n",
    "  <a href=\"../user_guides/exogenous-variables.html\">Exogenous Variables</a> section for more information on how to create window features and lags from exogenous variables.\n",
    "</p>\n",
    "\n",
    "</div>"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "0908f761",
   "metadata": {},
   "source": [
    "## Libraries and data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "d378f5ff-8092-49bb-80b7-8a3996d19fb1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Libraries\n",
    "# ==============================================================================\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "from lightgbm import LGBMRegressor\n",
    "from skforecast.datasets import fetch_dataset\n",
    "from skforecast.preprocessing import RollingFeatures\n",
    "from skforecast.recursive import ForecasterRecursive, ForecasterRecursiveMultiSeries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "e9cee83a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">╭────────────────────────────────────── <span style=\"font-weight: bold\">h2o</span> ───────────────────────────────────────╮\n",
       "│ <span style=\"font-weight: bold\">Description:</span>                                                                     │\n",
       "│ Monthly expenditure ($AUD) on corticosteroid drugs that the Australian health    │\n",
       "│ system had between 1991 and 2008.                                                │\n",
       "│                                                                                  │\n",
       "│ <span style=\"font-weight: bold\">Source:</span>                                                                          │\n",
       "│ Hyndman R (2023). fpp3: Data for Forecasting: Principles and Practice(3rd        │\n",
       "│ Edition). http://pkg.robjhyndman.com/fpp3package/,https://github.com/robjhyndman │\n",
       "│ /fpp3package, http://OTexts.com/fpp3.                                            │\n",
       "│                                                                                  │\n",
       "│ <span style=\"font-weight: bold\">URL:</span>                                                                             │\n",
       "│ https://raw.githubusercontent.com/skforecast/skforecast-                         │\n",
       "│ datasets/main/data/h2o.csv                                                       │\n",
       "│                                                                                  │\n",
       "│ <span style=\"font-weight: bold\">Shape:</span> 204 rows x 1 columns                                                      │\n",
       "╰──────────────────────────────────────────────────────────────────────────────────╯\n",
       "</pre>\n"
      ],
      "text/plain": [
       "╭────────────────────────────────────── \u001b[1mh2o\u001b[0m ───────────────────────────────────────╮\n",
       "│ \u001b[1mDescription:\u001b[0m                                                                     │\n",
       "│ Monthly expenditure ($AUD) on corticosteroid drugs that the Australian health    │\n",
       "│ system had between 1991 and 2008.                                                │\n",
       "│                                                                                  │\n",
       "│ \u001b[1mSource:\u001b[0m                                                                          │\n",
       "│ Hyndman R (2023). fpp3: Data for Forecasting: Principles and Practice(3rd        │\n",
       "│ Edition). http://pkg.robjhyndman.com/fpp3package/,https://github.com/robjhyndman │\n",
       "│ /fpp3package, http://OTexts.com/fpp3.                                            │\n",
       "│                                                                                  │\n",
       "│ \u001b[1mURL:\u001b[0m                                                                             │\n",
       "│ https://raw.githubusercontent.com/skforecast/skforecast-                         │\n",
       "│ datasets/main/data/h2o.csv                                                       │\n",
       "│                                                                                  │\n",
       "│ \u001b[1mShape:\u001b[0m 204 rows x 1 columns                                                      │\n",
       "╰──────────────────────────────────────────────────────────────────────────────────╯\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "datetime\n",
       "1991-07-01    0.429795\n",
       "1991-08-01    0.400906\n",
       "1991-09-01    0.432159\n",
       "1991-10-01    0.492543\n",
       "1991-11-01    0.502369\n",
       "                ...   \n",
       "2008-02-01    0.761822\n",
       "2008-03-01    0.649435\n",
       "2008-04-01    0.827887\n",
       "2008-05-01    0.816255\n",
       "2008-06-01    0.762137\n",
       "Freq: MS, Name: y, Length: 204, dtype: float64"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Data\n",
    "# ==============================================================================\n",
    "data = fetch_dataset(name=\"h2o\", raw=False)\n",
    "data.index.name = 'datetime'\n",
    "data = data.rename(columns={'x': 'y'})\n",
    "y = data['y']\n",
    "y"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "97f03864-ee4a-459d-9eec-03d14feb931e",
   "metadata": {},
   "source": [
    "## RollingFeatures"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "3d439250",
   "metadata": {},
   "source": [
    "The <code>RollingFeatures</code> class available in skforecast allows the creation of some of the most commonly used predictors:\n",
    "\n",
    "+ 'mean': the mean of the previous *n* values.\n",
    "+ 'std': the standard deviation of the previous *n* values.\n",
    "+ 'min': the minimum of the previous *n* values.\n",
    "+ 'max': the maximum of the previous *n* values.\n",
    "+ 'sum': the sum of the previous *n* values.\n",
    "+ 'median': the median of the previous *n* values.\n",
    "+ 'ratio_min_max': the ratio between the minimum and maximum of the previous *n* values.\n",
    "+ 'coef_variation': the coefficient of variation of the previous *n* values.\n",
    "+ 'ewm': the exponentially weighted mean of the previous *n* values. The decay factor `alpha` can be set in the `kwargs_stats` argument, default is `{'ewm': {'alpha': 0.3}}`.\n",
    "\n",
    "The user can specify these predictors by passing a list of strings to the `stats` argument. The user can also specify the window size for each of these predictors by passing a `list` of integers to the `window_size` argument, if the value is the same for all the predictors, the user can pass a single `integer`.\n",
    "\n",
    "The following example demonstrates how to use the <code>RollingFeatures</code> class to include rolling statistics (mean, minimum, and maximum values). Here, the rolling mean is computed with a window size of 10 and 20, while the minimum and maximum values use a window size of 10."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "76ed7bb5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Window features\n",
    "# ==============================================================================\n",
    "window_features = RollingFeatures(\n",
    "                      stats        = ['mean', 'mean', 'min', 'max'],\n",
    "                      window_sizes = [20, 10, 10, 10]\n",
    "                  )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "9afa7c24",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "    <style>\n",
       "        .container-1a7e87dd22a049378839034d05dbee20 {\n",
       "            font-family: 'Arial', sans-serif;\n",
       "            font-size: 0.9em;\n",
       "            color: #333333;\n",
       "            border: 1px solid #ddd;\n",
       "            background-color: #f0f8ff;\n",
       "            padding: 5px 15px;\n",
       "            border-radius: 8px;\n",
       "            max-width: 600px;\n",
       "            #margin: auto;\n",
       "        }\n",
       "        .container-1a7e87dd22a049378839034d05dbee20 h2 {\n",
       "            font-size: 1.5em;\n",
       "            color: #222222;\n",
       "            border-bottom: 2px solid #ddd;\n",
       "            padding-bottom: 5px;\n",
       "            margin-bottom: 15px;\n",
       "            margin-top: 5px;\n",
       "        }\n",
       "        .container-1a7e87dd22a049378839034d05dbee20 details {\n",
       "            margin: 10px 0;\n",
       "        }\n",
       "        .container-1a7e87dd22a049378839034d05dbee20 summary {\n",
       "            font-weight: bold;\n",
       "            font-size: 1.1em;\n",
       "            color: #000000;\n",
       "            cursor: pointer;\n",
       "            margin-bottom: 5px;\n",
       "            background-color: #b3dbfd;\n",
       "            padding: 5px;\n",
       "            border-radius: 5px;\n",
       "        }\n",
       "        .container-1a7e87dd22a049378839034d05dbee20 summary:hover {\n",
       "            color: #000000;\n",
       "            background-color: #e0e0e0;\n",
       "        }\n",
       "        .container-1a7e87dd22a049378839034d05dbee20 ul {\n",
       "            font-family: 'Courier New', monospace;\n",
       "            list-style-type: none;\n",
       "            padding-left: 20px;\n",
       "            margin: 10px 0;\n",
       "            line-height: normal;\n",
       "        }\n",
       "        .container-1a7e87dd22a049378839034d05dbee20 li {\n",
       "            margin: 5px 0;\n",
       "            font-family: 'Courier New', monospace;\n",
       "        }\n",
       "        .container-1a7e87dd22a049378839034d05dbee20 li strong {\n",
       "            font-weight: bold;\n",
       "            color: #444444;\n",
       "        }\n",
       "        .container-1a7e87dd22a049378839034d05dbee20 li::before {\n",
       "            content: \"- \";\n",
       "            color: #666666;\n",
       "        }\n",
       "        .container-1a7e87dd22a049378839034d05dbee20 a {\n",
       "            color: #001633;\n",
       "            text-decoration: none;\n",
       "        }\n",
       "        .container-1a7e87dd22a049378839034d05dbee20 a:hover {\n",
       "            color: #359ccb; \n",
       "        }\n",
       "    </style>\n",
       "    \n",
       "        <div class=\"container-1a7e87dd22a049378839034d05dbee20\">\n",
       "            <p style=\"font-size: 1.5em; font-weight: bold; margin-block-start: 0.83em; margin-block-end: 0.83em;\">ForecasterRecursive</p>\n",
       "            <details open>\n",
       "                <summary>General Information</summary>\n",
       "                <ul>\n",
       "                    <li><strong>Estimator:</strong> LGBMRegressor</li>\n",
       "                    <li><strong>Lags:</strong> [1 2 3]</li>\n",
       "                    <li><strong>Window features:</strong> ['roll_mean_20', 'roll_mean_10', 'roll_min_10', 'roll_max_10']</li>\n",
       "                    <li><strong>Window size:</strong> 20</li>\n",
       "                    <li><strong>Series name:</strong> y</li>\n",
       "                    <li><strong>Exogenous included:</strong> False</li>\n",
       "                    <li><strong>Weight function included:</strong> False</li>\n",
       "                    <li><strong>Differentiation order:</strong> None</li>\n",
       "                    <li><strong>Creation date:</strong> 2025-11-27 12:10:59</li>\n",
       "                    <li><strong>Last fit date:</strong> 2025-11-27 12:11:01</li>\n",
       "                    <li><strong>Skforecast version:</strong> 0.19.0</li>\n",
       "                    <li><strong>Python version:</strong> 3.12.11</li>\n",
       "                    <li><strong>Forecaster id:</strong> None</li>\n",
       "                </ul>\n",
       "            </details>\n",
       "            <details>\n",
       "                <summary>Exogenous Variables</summary>\n",
       "                <ul>\n",
       "                    None\n",
       "                </ul>\n",
       "            </details>\n",
       "            <details>\n",
       "                <summary>Data Transformations</summary>\n",
       "                <ul>\n",
       "                    <li><strong>Transformer for y:</strong> None</li>\n",
       "                    <li><strong>Transformer for exog:</strong> None</li>\n",
       "                </ul>\n",
       "            </details>\n",
       "            <details>\n",
       "                <summary>Training Information</summary>\n",
       "                <ul>\n",
       "                    <li><strong>Training range:</strong> [Timestamp('1991-07-01 00:00:00'), Timestamp('2008-06-01 00:00:00')]</li>\n",
       "                    <li><strong>Training index type:</strong> DatetimeIndex</li>\n",
       "                    <li><strong>Training index frequency:</strong> <MonthBegin></li>\n",
       "                </ul>\n",
       "            </details>\n",
       "            <details>\n",
       "                <summary>Estimator Parameters</summary>\n",
       "                <ul>\n",
       "                    {'boosting_type': 'gbdt', 'class_weight': None, 'colsample_bytree': 1.0, 'importance_type': 'split', 'learning_rate': 0.1, 'max_depth': -1, 'min_child_samples': 20, 'min_child_weight': 0.001, 'min_split_gain': 0.0, 'n_estimators': 100, 'n_jobs': None, 'num_leaves': 31, 'objective': None, 'random_state': 123, 'reg_alpha': 0.0, 'reg_lambda': 0.0, 'subsample': 1.0, 'subsample_for_bin': 200000, 'subsample_freq': 0, 'verbose': -1}\n",
       "                </ul>\n",
       "            </details>\n",
       "            <details>\n",
       "                <summary>Fit Kwargs</summary>\n",
       "                <ul>\n",
       "                    {}\n",
       "                </ul>\n",
       "            </details>\n",
       "            <p>\n",
       "                <a href=\"https://skforecast.org/0.19.0/api/forecasterrecursive.html\">&#128712 <strong>API Reference</strong></a>\n",
       "                &nbsp;&nbsp;\n",
       "                <a href=\"https://skforecast.org/0.19.0/user_guides/autoregressive-forecaster.html\">&#128462 <strong>User Guide</strong></a>\n",
       "            </p>\n",
       "        </div>\n",
       "        "
      ],
      "text/plain": [
       "=================== \n",
       "ForecasterRecursive \n",
       "=================== \n",
       "Estimator: LGBMRegressor \n",
       "Lags: [1 2 3] \n",
       "Window features: ['roll_mean_20', 'roll_mean_10', 'roll_min_10', 'roll_max_10'] \n",
       "Window size: 20 \n",
       "Series name: y \n",
       "Exogenous included: False \n",
       "Exogenous names: None \n",
       "Transformer for y: None \n",
       "Transformer for exog: None \n",
       "Weight function included: False \n",
       "Differentiation order: None \n",
       "Training range: [Timestamp('1991-07-01 00:00:00'), Timestamp('2008-06-01 00:00:00')] \n",
       "Training index type: DatetimeIndex \n",
       "Training index frequency: <MonthBegin> \n",
       "Estimator parameters: \n",
       "    {'boosting_type': 'gbdt', 'class_weight': None, 'colsample_bytree': 1.0,\n",
       "    'importance_type': 'split', 'learning_rate': 0.1, 'max_depth': -1,\n",
       "    'min_child_samples': 20, 'min_child_weight': 0.001, 'min_split_gain': 0.0,\n",
       "    'n_estimators': 100, 'n_jobs': None, 'num_leaves': 31, 'objective': None,\n",
       "    'random_state': 123, 'reg_alpha': 0.0, 'reg_lambda': 0.0, 'subsample': 1.0,\n",
       "    'subsample_for_bin': 200000, 'subsample_freq': 0, 'verbose': -1} \n",
       "fit_kwargs: {} \n",
       "Creation date: 2025-11-27 12:10:59 \n",
       "Last fit date: 2025-11-27 12:11:01 \n",
       "Skforecast version: 0.19.0 \n",
       "Python version: 3.12.11 \n",
       "Forecaster id: None "
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create and fit forecaster\n",
    "# ==============================================================================\n",
    "forecaster = ForecasterRecursive(\n",
    "                 estimator       = LGBMRegressor(random_state=123, verbose=-1),\n",
    "                 lags            = 3,\n",
    "                 window_features = window_features\n",
    "             )\n",
    "\n",
    "forecaster.fit(y=y)\n",
    "forecaster"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "f1bdf4f8-b999-4d97-899c-fbcc2af7066a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2008-07-01    0.784687\n",
       "2008-08-01    0.907246\n",
       "2008-09-01    1.078849\n",
       "Freq: MS, Name: pred, dtype: float64"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Predict\n",
    "# ==============================================================================\n",
    "steps = 36\n",
    "predictions = forecaster.predict(steps=steps)\n",
    "predictions.head(3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a0a25cc4",
   "metadata": {},
   "source": [
    "The window size needed by this Forecaster is the maximum of the window sizes between the lagged values and the rolling features. In this case, this value is 20."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "757bdd0a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Window size lags            :  3\n",
      "Window size window features :  20\n",
      "Window size Forecaster      :  20\n"
     ]
    }
   ],
   "source": [
    "# Predict\n",
    "# ==============================================================================\n",
    "print(\"Window size lags            : \", forecaster.max_lag)\n",
    "print(\"Window size window features : \", forecaster.max_size_window_features)\n",
    "print(\"Window size Forecaster      : \", forecaster.window_size)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0050263a",
   "metadata": {},
   "source": [
    "Additional arguments can be passed to the `RollingFeatures`:\n",
    "\n",
    "+ `features_names`: By default, feature names follow the pattern `roll_<stat>_<window_size>`. For instance, a rolling mean with a window size of 20 is named `roll_mean_20`. Users can also assign custom names to each feature using a `list` of strings.\n",
    "\n",
    "+ `min_periods`: allows specifying the minimum number of observations required to compute the statistics during the training matrix generation (same as the `min_periods` argument of [pandas rolling](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.rolling.html)). It can be a single integer or a list of integers, one for each statistic.\n",
    "\n",
    "+ `fill_na`: define the strategy for handling missing values during the training matrix generation. Available methods are: `'mean'`, `'median'`, `'ffill'`, `'bfill'`, or a `float` value.\n",
    "\n",
    "By inspecting the training matrices, it is possible to check that the rolling features have been correctly included."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "08956146-2b7e-41ad-8454-246e9d35f8a3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>lag_1</th>\n",
       "      <th>lag_2</th>\n",
       "      <th>lag_3</th>\n",
       "      <th>roll_mean_20</th>\n",
       "      <th>roll_mean_10</th>\n",
       "      <th>roll_min_10</th>\n",
       "      <th>roll_max_10</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>datetime</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1993-03-01</th>\n",
       "      <td>0.387554</td>\n",
       "      <td>0.751503</td>\n",
       "      <td>0.771258</td>\n",
       "      <td>0.496401</td>\n",
       "      <td>0.534009</td>\n",
       "      <td>0.361801</td>\n",
       "      <td>0.771258</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1993-04-01</th>\n",
       "      <td>0.427283</td>\n",
       "      <td>0.387554</td>\n",
       "      <td>0.751503</td>\n",
       "      <td>0.496275</td>\n",
       "      <td>0.540557</td>\n",
       "      <td>0.387554</td>\n",
       "      <td>0.771258</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1993-05-01</th>\n",
       "      <td>0.413890</td>\n",
       "      <td>0.427283</td>\n",
       "      <td>0.387554</td>\n",
       "      <td>0.496924</td>\n",
       "      <td>0.540893</td>\n",
       "      <td>0.387554</td>\n",
       "      <td>0.771258</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1993-06-01</th>\n",
       "      <td>0.428859</td>\n",
       "      <td>0.413890</td>\n",
       "      <td>0.427283</td>\n",
       "      <td>0.496759</td>\n",
       "      <td>0.535440</td>\n",
       "      <td>0.387554</td>\n",
       "      <td>0.771258</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1993-07-01</th>\n",
       "      <td>0.470126</td>\n",
       "      <td>0.428859</td>\n",
       "      <td>0.413890</td>\n",
       "      <td>0.495638</td>\n",
       "      <td>0.534906</td>\n",
       "      <td>0.387554</td>\n",
       "      <td>0.771258</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2008-02-01</th>\n",
       "      <td>1.219941</td>\n",
       "      <td>1.176589</td>\n",
       "      <td>1.163534</td>\n",
       "      <td>0.980390</td>\n",
       "      <td>0.995834</td>\n",
       "      <td>0.561760</td>\n",
       "      <td>1.219941</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2008-03-01</th>\n",
       "      <td>0.761822</td>\n",
       "      <td>1.219941</td>\n",
       "      <td>1.176589</td>\n",
       "      <td>0.978582</td>\n",
       "      <td>1.015840</td>\n",
       "      <td>0.745258</td>\n",
       "      <td>1.219941</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2008-04-01</th>\n",
       "      <td>0.649435</td>\n",
       "      <td>0.761822</td>\n",
       "      <td>1.219941</td>\n",
       "      <td>0.966838</td>\n",
       "      <td>1.006258</td>\n",
       "      <td>0.649435</td>\n",
       "      <td>1.219941</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2008-05-01</th>\n",
       "      <td>0.827887</td>\n",
       "      <td>0.649435</td>\n",
       "      <td>0.761822</td>\n",
       "      <td>0.955750</td>\n",
       "      <td>1.005253</td>\n",
       "      <td>0.649435</td>\n",
       "      <td>1.219941</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2008-06-01</th>\n",
       "      <td>0.816255</td>\n",
       "      <td>0.827887</td>\n",
       "      <td>0.649435</td>\n",
       "      <td>0.946778</td>\n",
       "      <td>0.991464</td>\n",
       "      <td>0.649435</td>\n",
       "      <td>1.219941</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>184 rows × 7 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "               lag_1     lag_2     lag_3  roll_mean_20  roll_mean_10  \\\n",
       "datetime                                                               \n",
       "1993-03-01  0.387554  0.751503  0.771258      0.496401      0.534009   \n",
       "1993-04-01  0.427283  0.387554  0.751503      0.496275      0.540557   \n",
       "1993-05-01  0.413890  0.427283  0.387554      0.496924      0.540893   \n",
       "1993-06-01  0.428859  0.413890  0.427283      0.496759      0.535440   \n",
       "1993-07-01  0.470126  0.428859  0.413890      0.495638      0.534906   \n",
       "...              ...       ...       ...           ...           ...   \n",
       "2008-02-01  1.219941  1.176589  1.163534      0.980390      0.995834   \n",
       "2008-03-01  0.761822  1.219941  1.176589      0.978582      1.015840   \n",
       "2008-04-01  0.649435  0.761822  1.219941      0.966838      1.006258   \n",
       "2008-05-01  0.827887  0.649435  0.761822      0.955750      1.005253   \n",
       "2008-06-01  0.816255  0.827887  0.649435      0.946778      0.991464   \n",
       "\n",
       "            roll_min_10  roll_max_10  \n",
       "datetime                              \n",
       "1993-03-01     0.361801     0.771258  \n",
       "1993-04-01     0.387554     0.771258  \n",
       "1993-05-01     0.387554     0.771258  \n",
       "1993-06-01     0.387554     0.771258  \n",
       "1993-07-01     0.387554     0.771258  \n",
       "...                 ...          ...  \n",
       "2008-02-01     0.561760     1.219941  \n",
       "2008-03-01     0.745258     1.219941  \n",
       "2008-04-01     0.649435     1.219941  \n",
       "2008-05-01     0.649435     1.219941  \n",
       "2008-06-01     0.649435     1.219941  \n",
       "\n",
       "[184 rows x 7 columns]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Training matrices used internally to fit the estimator\n",
    "# ==============================================================================\n",
    "X_train, y_train = forecaster.create_train_X_y(y=y)\n",
    "X_train"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e2f5f51c",
   "metadata": {},
   "source": [
    "It is also possible to use the <code>RollingFeatures</code> class outside the forecaster to gain a deeper insight into its behaviour. The `transform` method computes the rolling features for a given numpy array, which is assumed to contain as many past observations as the maximum window size required to compute the features. The output is a numpy array with the rolling features."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "eac1be35",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 9.5, 14.5, 10. , 19. ])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create rolling features from a given array\n",
    "# ==============================================================================\n",
    "x = np.arange(20)\n",
    "window_features.transform(X=x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bb241389",
   "metadata": {},
   "source": [
    "The `transform_batch` method is designed to transform a whole pandas Series from which multiple rolling windows can be extracted. The output is a pandas DataFrame with the rolling features."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "7e1d5c7f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>roll_mean_20</th>\n",
       "      <th>roll_mean_10</th>\n",
       "      <th>roll_min_10</th>\n",
       "      <th>roll_max_10</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>datetime</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1993-03-01</th>\n",
       "      <td>0.496401</td>\n",
       "      <td>0.534009</td>\n",
       "      <td>0.361801</td>\n",
       "      <td>0.771258</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1993-04-01</th>\n",
       "      <td>0.496275</td>\n",
       "      <td>0.540557</td>\n",
       "      <td>0.387554</td>\n",
       "      <td>0.771258</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1993-05-01</th>\n",
       "      <td>0.496924</td>\n",
       "      <td>0.540893</td>\n",
       "      <td>0.387554</td>\n",
       "      <td>0.771258</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            roll_mean_20  roll_mean_10  roll_min_10  roll_max_10\n",
       "datetime                                                        \n",
       "1993-03-01      0.496401      0.534009     0.361801     0.771258\n",
       "1993-04-01      0.496275      0.540557     0.387554     0.771258\n",
       "1993-05-01      0.496924      0.540893     0.387554     0.771258"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create rolling features from a pandas series\n",
    "# ==============================================================================\n",
    "window_features.transform_batch(y).head(3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d8e8dc20",
   "metadata": {},
   "source": [
    "The reason for these two different data transformation methods is that the first is used during prediction, where the forecaster only has access to the last window of the series. In contrast, the second is used during training, where the forecaster has access to the entire series."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "63623cfc",
   "metadata": {},
   "source": [
    "## Create your custom window features\n",
    "\n",
    "<code>RollingFeatures</code> is very useful for including some of the most commonly used predictors.  However, users may need to include additional predictors that are not provided by this class. In such cases, users can create their own custom class to compute the desired features and include them in the forecaster.\n",
    "\n",
    "The custom class must have these 2 methods:\n",
    "\n",
    "+ `transform_batch`: method to compute the features in batch from a pandas Series. This method will be used to compute the features during the training process. It must return a pandas DataFrame containing the rolling features.\n",
    "\n",
    "+ `transform`: method to compute the features from a numpy array. This method will be used to compute the features during the prediction process. It must return a numpy array containing the computed statistics.\n",
    "\n",
    "and these 2 attributes:\n",
    "\n",
    "+ `window_sizes`: size of the rolling window required to compute the features. It must be a list of integers.\n",
    "\n",
    "+ `features_names`: list with the names of the output features. It must be a list of strings.\n",
    "\n",
    "The follwing example shows how to create a custom class to include the rolling skewness and kurtosis with a window size of 20."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6c4f19b6",
   "metadata": {},
   "source": [
    "<div class=\"admonition note\" name=\"html-admonition\" style=\"background: rgba(0,191,191,.1); padding-top: 0px; padding-bottom: 6px; border-radius: 8px; border-left: 8px solid #00bfa5; border-color: #00bfa5; padding-left: 10px; padding-right: 10px;\">\n",
    "\n",
    "<p class=\"title\">\n",
    "    <i style=\"font-size: 18px; color:#00bfa5;\"></i>\n",
    "    <b style=\"color: #00bfa5;\">&#128161 Tip</b>\n",
    "</p>\n",
    "\n",
    "If you have any doubt when creating your custom class, you can check the source code of the <code>RollingFeatures</code> class available in the <a href=\"../api/preprocessing.html#skforecast.preprocessing.preprocessing.RollingFeatures\">API Reference</a>.\n",
    "\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "9f6acbec",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Custom class to create rolling skewness features\n",
    "# ==============================================================================\n",
    "from scipy.stats import skew\n",
    "\n",
    "\n",
    "class RollingSkewness():\n",
    "    \"\"\"\n",
    "    Custom class to create rolling skewness features.\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(self, window_sizes, features_names: list = 'rolling_skewness'):\n",
    "        \n",
    "        if not isinstance(window_sizes, list):\n",
    "            window_sizes = [window_sizes]\n",
    "        self.window_sizes = window_sizes\n",
    "        self.features_names = features_names\n",
    "\n",
    "    def transform_batch(self, X: pd.Series) -> pd.DataFrame:\n",
    "        \n",
    "        rolling_obj = X.rolling(window=self.window_sizes[0], center=False, closed='left')\n",
    "        rolling_skewness = rolling_obj.skew()\n",
    "        rolling_skewness = pd.DataFrame({\n",
    "                               self.features_names: rolling_skewness\n",
    "                           }).dropna()\n",
    "\n",
    "        return rolling_skewness\n",
    "\n",
    "    def transform(self, X: np.ndarray) -> np.ndarray:\n",
    "        \n",
    "        X = X[~np.isnan(X)]\n",
    "        if len(X) > 0:\n",
    "            rolling_skewness = np.array([skew(X, bias=False)])\n",
    "        else:\n",
    "            rolling_skewness = np.array([np.nan])\n",
    "        \n",
    "        return rolling_skewness"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "70760ed4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>rolling_skewness</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>datetime</th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1991-10-01</th>\n",
       "      <td>-1.696160</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1991-11-01</th>\n",
       "      <td>0.897261</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1991-12-01</th>\n",
       "      <td>-1.602797</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1992-01-01</th>\n",
       "      <td>1.681518</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1992-02-01</th>\n",
       "      <td>-0.778727</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2008-02-01</th>\n",
       "      <td>1.359033</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2008-03-01</th>\n",
       "      <td>-1.674974</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2008-04-01</th>\n",
       "      <td>1.466482</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2008-05-01</th>\n",
       "      <td>-0.747574</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2008-06-01</th>\n",
       "      <td>-1.705640</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>201 rows × 1 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "            rolling_skewness\n",
       "datetime                    \n",
       "1991-10-01         -1.696160\n",
       "1991-11-01          0.897261\n",
       "1991-12-01         -1.602797\n",
       "1992-01-01          1.681518\n",
       "1992-02-01         -0.778727\n",
       "...                      ...\n",
       "2008-02-01          1.359033\n",
       "2008-03-01         -1.674974\n",
       "2008-04-01          1.466482\n",
       "2008-05-01         -0.747574\n",
       "2008-06-01         -1.705640\n",
       "\n",
       "[201 rows x 1 columns]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Transform batch\n",
    "# ==============================================================================\n",
    "window_features = RollingSkewness(window_sizes=3)\n",
    "window_features.transform_batch(y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "e72cdf99",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.93521953])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Transform\n",
    "# ==============================================================================\n",
    "window_features.transform(X=np.array([6, 12, 8]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "5566caab",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2008-07-01    0.769870\n",
       "2008-08-01    0.824683\n",
       "2008-09-01    0.819595\n",
       "2008-10-01    0.799849\n",
       "2008-11-01    0.802432\n",
       "Freq: MS, Name: pred, dtype: float64"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Forecaster with custom rolling features\n",
    "# ==============================================================================\n",
    "forecaster = ForecasterRecursive(\n",
    "                 estimator       = LGBMRegressor(random_state=123, n_jobs=-1, verbose=-1),\n",
    "                 lags            = 3,\n",
    "                 window_features = window_features\n",
    "             )\n",
    "\n",
    "forecaster.fit(y=y)\n",
    "forecaster.predict(steps=5)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1c1483f2",
   "metadata": {},
   "source": [
    "## Create your custom window features ForecasterRecursiveMultiSeries\n",
    "\n",
    "When using a <code>ForecasterRecursiveMultiSeries</code>, the `transform` method must return a numpy array that calculates all the features for all the series contained in `last_window` at once."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "652460fd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">╭─────────────────────── <span style=\"font-weight: bold\">items_sales</span> ───────────────────────╮\n",
       "│ <span style=\"font-weight: bold\">Description:</span>                                              │\n",
       "│ Simulated time series for the sales of 3 different items. │\n",
       "│                                                           │\n",
       "│ <span style=\"font-weight: bold\">Source:</span>                                                   │\n",
       "│ Simulated data.                                           │\n",
       "│                                                           │\n",
       "│ <span style=\"font-weight: bold\">URL:</span>                                                      │\n",
       "│ https://raw.githubusercontent.com/skforecast/skforecast-  │\n",
       "│ datasets/main/data/simulated_items_sales.csv              │\n",
       "│                                                           │\n",
       "│ <span style=\"font-weight: bold\">Shape:</span> 1097 rows x 3 columns                              │\n",
       "╰───────────────────────────────────────────────────────────╯\n",
       "</pre>\n"
      ],
      "text/plain": [
       "╭─────────────────────── \u001b[1mitems_sales\u001b[0m ───────────────────────╮\n",
       "│ \u001b[1mDescription:\u001b[0m                                              │\n",
       "│ Simulated time series for the sales of 3 different items. │\n",
       "│                                                           │\n",
       "│ \u001b[1mSource:\u001b[0m                                                   │\n",
       "│ Simulated data.                                           │\n",
       "│                                                           │\n",
       "│ \u001b[1mURL:\u001b[0m                                                      │\n",
       "│ https://raw.githubusercontent.com/skforecast/skforecast-  │\n",
       "│ datasets/main/data/simulated_items_sales.csv              │\n",
       "│                                                           │\n",
       "│ \u001b[1mShape:\u001b[0m 1097 rows x 3 columns                              │\n",
       "╰───────────────────────────────────────────────────────────╯\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>item_1</th>\n",
       "      <th>item_2</th>\n",
       "      <th>item_3</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2012-01-01</th>\n",
       "      <td>8.253175</td>\n",
       "      <td>21.047727</td>\n",
       "      <td>19.429739</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2012-01-02</th>\n",
       "      <td>22.777826</td>\n",
       "      <td>26.578125</td>\n",
       "      <td>28.009863</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2012-01-03</th>\n",
       "      <td>27.549099</td>\n",
       "      <td>31.751042</td>\n",
       "      <td>32.078922</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2012-01-04</th>\n",
       "      <td>25.895533</td>\n",
       "      <td>24.567708</td>\n",
       "      <td>27.252276</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2012-01-05</th>\n",
       "      <td>21.379238</td>\n",
       "      <td>18.191667</td>\n",
       "      <td>20.357737</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "               item_1     item_2     item_3\n",
       "date                                       \n",
       "2012-01-01   8.253175  21.047727  19.429739\n",
       "2012-01-02  22.777826  26.578125  28.009863\n",
       "2012-01-03  27.549099  31.751042  32.078922\n",
       "2012-01-04  25.895533  24.567708  27.252276\n",
       "2012-01-05  21.379238  18.191667  20.357737"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Data download\n",
    "# ==============================================================================\n",
    "data_multiseries = fetch_dataset(name=\"items_sales\")\n",
    "data_multiseries.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "1fc12889",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Custom class to create rolling skewness features (multi-series)\n",
    "# ==============================================================================\n",
    "from scipy.stats import skew\n",
    "\n",
    "\n",
    "class RollingSkewnessMultiSeries():\n",
    "    \"\"\"\n",
    "    Custom class to create rolling skewness features for multiple series.\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(self, window_sizes, features_names: list = 'rolling_skewness'):\n",
    "        \n",
    "        if not isinstance(window_sizes, list):\n",
    "            window_sizes = [window_sizes]\n",
    "        self.window_sizes = window_sizes\n",
    "        self.features_names = features_names\n",
    "\n",
    "    def transform_batch(self, X: pd.Series) -> pd.DataFrame:\n",
    "        \n",
    "        rolling_obj = X.rolling(window=self.window_sizes[0], center=False, closed='left')\n",
    "        rolling_skewness = rolling_obj.skew()\n",
    "        rolling_skewness = pd.DataFrame({\n",
    "                               self.features_names: rolling_skewness\n",
    "                           }).dropna()\n",
    "\n",
    "        return rolling_skewness\n",
    "\n",
    "    def transform(self, X: np.ndarray) -> np.ndarray:\n",
    "        \n",
    "        X_dim = X.ndim\n",
    "        if X_dim == 1:\n",
    "            n_series = 1  # Only one series\n",
    "            X = X.reshape(-1, 1)\n",
    "        else:\n",
    "            n_series = X.shape[1]  # Series (levels) to be predicted (present in last_window)\n",
    "        \n",
    "        n_stats = 1  # Only skewness is calculated\n",
    "        rolling_skewness = np.full(\n",
    "            shape=(n_series, n_stats), fill_value=np.nan, dtype=float\n",
    "        )\n",
    "        for i in range(n_series):\n",
    "            if len(X) > 0:\n",
    "                rolling_skewness[i, :] = skew(X[:, i], bias=False)\n",
    "            else:\n",
    "                rolling_skewness[i, :] = np.nan      \n",
    "\n",
    "        if X_dim == 1:\n",
    "            rolling_skewness = rolling_skewness.flatten()  \n",
    "        \n",
    "        return rolling_skewness"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "b708b3f8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╭────────────────────────────────── InputTypeWarning ──────────────────────────────────╮</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Passing a DataFrame (either wide or long format) as `series` requires additional     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> internal transformations, which can increase computational time. It is recommended   <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> to use a dictionary of pandas Series instead. For more details, see:                 <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> https://skforecast.org/latest/user_guides/independent-multi-time-series-forecasting. <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> html#input-data                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>                                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Category : skforecast.exceptions.InputTypeWarning                                    <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Location :                                                                           <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> c:\\Users\\jaesc2\\Miniconda3\\envs\\skforecast_py12\\Lib\\site-packages\\skforecast\\utils\\u <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> tils.py:2349                                                                         <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Suppress : warnings.simplefilter('ignore', category=InputTypeWarning)                <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╰──────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[38;5;214m╭─\u001b[0m\u001b[38;5;214m─────────────────────────────────\u001b[0m\u001b[38;5;214m InputTypeWarning \u001b[0m\u001b[38;5;214m─────────────────────────────────\u001b[0m\u001b[38;5;214m─╮\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Passing a DataFrame (either wide or long format) as `series` requires additional     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m internal transformations, which can increase computational time. It is recommended   \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m to use a dictionary of pandas Series instead. For more details, see:                 \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m https://skforecast.org/latest/user_guides/independent-multi-time-series-forecasting. \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m html#input-data                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m                                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Category : skforecast.exceptions.InputTypeWarning                                    \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Location :                                                                           \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m c:\\Users\\jaesc2\\Miniconda3\\envs\\skforecast_py12\\Lib\\site-packages\\skforecast\\utils\\u \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m tils.py:2349                                                                         \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Suppress : warnings.simplefilter('ignore', category=InputTypeWarning)                \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m╰──────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>level</th>\n",
       "      <th>pred</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2015-01-02</th>\n",
       "      <td>item_1</td>\n",
       "      <td>13.530901</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-02</th>\n",
       "      <td>item_2</td>\n",
       "      <td>19.709656</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-02</th>\n",
       "      <td>item_3</td>\n",
       "      <td>19.378026</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-03</th>\n",
       "      <td>item_1</td>\n",
       "      <td>14.252429</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-03</th>\n",
       "      <td>item_2</td>\n",
       "      <td>18.608582</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-03</th>\n",
       "      <td>item_3</td>\n",
       "      <td>20.457204</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-04</th>\n",
       "      <td>item_1</td>\n",
       "      <td>14.230324</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-04</th>\n",
       "      <td>item_2</td>\n",
       "      <td>19.536894</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-04</th>\n",
       "      <td>item_3</td>\n",
       "      <td>21.238047</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-05</th>\n",
       "      <td>item_1</td>\n",
       "      <td>16.339439</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-05</th>\n",
       "      <td>item_2</td>\n",
       "      <td>19.174911</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-05</th>\n",
       "      <td>item_3</td>\n",
       "      <td>21.039226</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-06</th>\n",
       "      <td>item_1</td>\n",
       "      <td>17.231169</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-06</th>\n",
       "      <td>item_2</td>\n",
       "      <td>18.821718</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-06</th>\n",
       "      <td>item_3</td>\n",
       "      <td>19.032785</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "             level       pred\n",
       "2015-01-02  item_1  13.530901\n",
       "2015-01-02  item_2  19.709656\n",
       "2015-01-02  item_3  19.378026\n",
       "2015-01-03  item_1  14.252429\n",
       "2015-01-03  item_2  18.608582\n",
       "2015-01-03  item_3  20.457204\n",
       "2015-01-04  item_1  14.230324\n",
       "2015-01-04  item_2  19.536894\n",
       "2015-01-04  item_3  21.238047\n",
       "2015-01-05  item_1  16.339439\n",
       "2015-01-05  item_2  19.174911\n",
       "2015-01-05  item_3  21.039226\n",
       "2015-01-06  item_1  17.231169\n",
       "2015-01-06  item_2  18.821718\n",
       "2015-01-06  item_3  19.032785"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Forecaster with custom rolling features\n",
    "# ==============================================================================\n",
    "window_features = RollingSkewnessMultiSeries(window_sizes=3)\n",
    "forecaster = ForecasterRecursiveMultiSeries(\n",
    "                 estimator       = LGBMRegressor(random_state=123, verbose=-1),\n",
    "                 lags            = 3,\n",
    "                 window_features = window_features,\n",
    "                 encoding        = 'ordinal'\n",
    "             )\n",
    "\n",
    "forecaster.fit(series=data_multiseries)\n",
    "forecaster.predict(steps=5, levels=None)  # Predict all levels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "23d9f952",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-1.7304836 ],\n",
       "       [ 1.69345527],\n",
       "       [ 0.27695088]])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Transform output multi-series shape (n_levels, n_stats)\n",
    "# ==============================================================================\n",
    "window_features.transform(pd.DataFrame(forecaster.last_window_).to_numpy())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "672a4286",
   "metadata": {},
   "source": [
    "## Adding multiple window features\n",
    "\n",
    "It is possible to include multiple window features in all forecasters. The `window_features` argument must be a list of instances of the classes that compute the desired features."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "e07e3666",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "    <style>\n",
       "        .container-83ffe6ee0cc940bdb07479cf4dc6d2bb {\n",
       "            font-family: 'Arial', sans-serif;\n",
       "            font-size: 0.9em;\n",
       "            color: #333333;\n",
       "            border: 1px solid #ddd;\n",
       "            background-color: #f0f8ff;\n",
       "            padding: 5px 15px;\n",
       "            border-radius: 8px;\n",
       "            max-width: 600px;\n",
       "            #margin: auto;\n",
       "        }\n",
       "        .container-83ffe6ee0cc940bdb07479cf4dc6d2bb h2 {\n",
       "            font-size: 1.5em;\n",
       "            color: #222222;\n",
       "            border-bottom: 2px solid #ddd;\n",
       "            padding-bottom: 5px;\n",
       "            margin-bottom: 15px;\n",
       "            margin-top: 5px;\n",
       "        }\n",
       "        .container-83ffe6ee0cc940bdb07479cf4dc6d2bb details {\n",
       "            margin: 10px 0;\n",
       "        }\n",
       "        .container-83ffe6ee0cc940bdb07479cf4dc6d2bb summary {\n",
       "            font-weight: bold;\n",
       "            font-size: 1.1em;\n",
       "            color: #000000;\n",
       "            cursor: pointer;\n",
       "            margin-bottom: 5px;\n",
       "            background-color: #b3dbfd;\n",
       "            padding: 5px;\n",
       "            border-radius: 5px;\n",
       "        }\n",
       "        .container-83ffe6ee0cc940bdb07479cf4dc6d2bb summary:hover {\n",
       "            color: #000000;\n",
       "            background-color: #e0e0e0;\n",
       "        }\n",
       "        .container-83ffe6ee0cc940bdb07479cf4dc6d2bb ul {\n",
       "            font-family: 'Courier New', monospace;\n",
       "            list-style-type: none;\n",
       "            padding-left: 20px;\n",
       "            margin: 10px 0;\n",
       "            line-height: normal;\n",
       "        }\n",
       "        .container-83ffe6ee0cc940bdb07479cf4dc6d2bb li {\n",
       "            margin: 5px 0;\n",
       "            font-family: 'Courier New', monospace;\n",
       "        }\n",
       "        .container-83ffe6ee0cc940bdb07479cf4dc6d2bb li strong {\n",
       "            font-weight: bold;\n",
       "            color: #444444;\n",
       "        }\n",
       "        .container-83ffe6ee0cc940bdb07479cf4dc6d2bb li::before {\n",
       "            content: \"- \";\n",
       "            color: #666666;\n",
       "        }\n",
       "        .container-83ffe6ee0cc940bdb07479cf4dc6d2bb a {\n",
       "            color: #001633;\n",
       "            text-decoration: none;\n",
       "        }\n",
       "        .container-83ffe6ee0cc940bdb07479cf4dc6d2bb a:hover {\n",
       "            color: #359ccb; \n",
       "        }\n",
       "    </style>\n",
       "    \n",
       "        <div class=\"container-83ffe6ee0cc940bdb07479cf4dc6d2bb\">\n",
       "            <p style=\"font-size: 1.5em; font-weight: bold; margin-block-start: 0.83em; margin-block-end: 0.83em;\">ForecasterRecursive</p>\n",
       "            <details open>\n",
       "                <summary>General Information</summary>\n",
       "                <ul>\n",
       "                    <li><strong>Estimator:</strong> LGBMRegressor</li>\n",
       "                    <li><strong>Lags:</strong> [1 2 3]</li>\n",
       "                    <li><strong>Window features:</strong> ['roll_mean_20', 'roll_mean_10', 'rolling_skewness']</li>\n",
       "                    <li><strong>Window size:</strong> 20</li>\n",
       "                    <li><strong>Series name:</strong> y</li>\n",
       "                    <li><strong>Exogenous included:</strong> False</li>\n",
       "                    <li><strong>Weight function included:</strong> False</li>\n",
       "                    <li><strong>Differentiation order:</strong> None</li>\n",
       "                    <li><strong>Creation date:</strong> 2025-11-27 12:11:03</li>\n",
       "                    <li><strong>Last fit date:</strong> 2025-11-27 12:11:03</li>\n",
       "                    <li><strong>Skforecast version:</strong> 0.19.0</li>\n",
       "                    <li><strong>Python version:</strong> 3.12.11</li>\n",
       "                    <li><strong>Forecaster id:</strong> None</li>\n",
       "                </ul>\n",
       "            </details>\n",
       "            <details>\n",
       "                <summary>Exogenous Variables</summary>\n",
       "                <ul>\n",
       "                    None\n",
       "                </ul>\n",
       "            </details>\n",
       "            <details>\n",
       "                <summary>Data Transformations</summary>\n",
       "                <ul>\n",
       "                    <li><strong>Transformer for y:</strong> None</li>\n",
       "                    <li><strong>Transformer for exog:</strong> None</li>\n",
       "                </ul>\n",
       "            </details>\n",
       "            <details>\n",
       "                <summary>Training Information</summary>\n",
       "                <ul>\n",
       "                    <li><strong>Training range:</strong> [Timestamp('1991-07-01 00:00:00'), Timestamp('2008-06-01 00:00:00')]</li>\n",
       "                    <li><strong>Training index type:</strong> DatetimeIndex</li>\n",
       "                    <li><strong>Training index frequency:</strong> <MonthBegin></li>\n",
       "                </ul>\n",
       "            </details>\n",
       "            <details>\n",
       "                <summary>Estimator Parameters</summary>\n",
       "                <ul>\n",
       "                    {'boosting_type': 'gbdt', 'class_weight': None, 'colsample_bytree': 1.0, 'importance_type': 'split', 'learning_rate': 0.1, 'max_depth': -1, 'min_child_samples': 20, 'min_child_weight': 0.001, 'min_split_gain': 0.0, 'n_estimators': 100, 'n_jobs': None, 'num_leaves': 31, 'objective': None, 'random_state': 123, 'reg_alpha': 0.0, 'reg_lambda': 0.0, 'subsample': 1.0, 'subsample_for_bin': 200000, 'subsample_freq': 0, 'verbose': -1}\n",
       "                </ul>\n",
       "            </details>\n",
       "            <details>\n",
       "                <summary>Fit Kwargs</summary>\n",
       "                <ul>\n",
       "                    {}\n",
       "                </ul>\n",
       "            </details>\n",
       "            <p>\n",
       "                <a href=\"https://skforecast.org/0.19.0/api/forecasterrecursive.html\">&#128712 <strong>API Reference</strong></a>\n",
       "                &nbsp;&nbsp;\n",
       "                <a href=\"https://skforecast.org/0.19.0/user_guides/autoregressive-forecaster.html\">&#128462 <strong>User Guide</strong></a>\n",
       "            </p>\n",
       "        </div>\n",
       "        "
      ],
      "text/plain": [
       "=================== \n",
       "ForecasterRecursive \n",
       "=================== \n",
       "Estimator: LGBMRegressor \n",
       "Lags: [1 2 3] \n",
       "Window features: ['roll_mean_20', 'roll_mean_10', 'rolling_skewness'] \n",
       "Window size: 20 \n",
       "Series name: y \n",
       "Exogenous included: False \n",
       "Exogenous names: None \n",
       "Transformer for y: None \n",
       "Transformer for exog: None \n",
       "Weight function included: False \n",
       "Differentiation order: None \n",
       "Training range: [Timestamp('1991-07-01 00:00:00'), Timestamp('2008-06-01 00:00:00')] \n",
       "Training index type: DatetimeIndex \n",
       "Training index frequency: <MonthBegin> \n",
       "Estimator parameters: \n",
       "    {'boosting_type': 'gbdt', 'class_weight': None, 'colsample_bytree': 1.0,\n",
       "    'importance_type': 'split', 'learning_rate': 0.1, 'max_depth': -1,\n",
       "    'min_child_samples': 20, 'min_child_weight': 0.001, 'min_split_gain': 0.0,\n",
       "    'n_estimators': 100, 'n_jobs': None, 'num_leaves': 31, 'objective': None,\n",
       "    'random_state': 123, 'reg_alpha': 0.0, 'reg_lambda': 0.0, 'subsample': 1.0,\n",
       "    'subsample_for_bin': 200000, 'subsample_freq': 0, 'verbose': -1} \n",
       "fit_kwargs: {} \n",
       "Creation date: 2025-11-27 12:11:03 \n",
       "Last fit date: 2025-11-27 12:11:03 \n",
       "Skforecast version: 0.19.0 \n",
       "Python version: 3.12.11 \n",
       "Forecaster id: None "
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Forecaster with multiple window features\n",
    "# ==============================================================================\n",
    "window_features = [\n",
    "    RollingFeatures(stats=['mean', 'mean'], window_sizes=[20, 10]),\n",
    "    RollingSkewness(window_sizes=10)\n",
    "]\n",
    "\n",
    "forecaster = ForecasterRecursive(\n",
    "                 estimator       = LGBMRegressor(random_state=123, verbose=-1),\n",
    "                 lags            = 3,\n",
    "                 window_features = window_features\n",
    "             )\n",
    "\n",
    "forecaster.fit(y=y)\n",
    "forecaster"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "fb15aad1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>lag_1</th>\n",
       "      <th>lag_2</th>\n",
       "      <th>lag_3</th>\n",
       "      <th>roll_mean_20</th>\n",
       "      <th>roll_mean_10</th>\n",
       "      <th>rolling_skewness</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2008-07-01</th>\n",
       "      <td>0.762137</td>\n",
       "      <td>0.816255</td>\n",
       "      <td>0.827887</td>\n",
       "      <td>0.926472</td>\n",
       "      <td>0.959856</td>\n",
       "      <td>-0.130309</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2008-08-01</th>\n",
       "      <td>0.953737</td>\n",
       "      <td>0.762137</td>\n",
       "      <td>0.816255</td>\n",
       "      <td>0.918757</td>\n",
       "      <td>0.944132</td>\n",
       "      <td>-0.053265</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2008-09-01</th>\n",
       "      <td>1.027884</td>\n",
       "      <td>0.953737</td>\n",
       "      <td>0.762137</td>\n",
       "      <td>0.914148</td>\n",
       "      <td>0.935922</td>\n",
       "      <td>-0.024878</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2008-10-01</th>\n",
       "      <td>0.963651</td>\n",
       "      <td>1.027884</td>\n",
       "      <td>0.953737</td>\n",
       "      <td>0.901165</td>\n",
       "      <td>0.915934</td>\n",
       "      <td>-0.022704</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2008-11-01</th>\n",
       "      <td>1.096952</td>\n",
       "      <td>0.963651</td>\n",
       "      <td>1.027884</td>\n",
       "      <td>0.926125</td>\n",
       "      <td>0.907970</td>\n",
       "      <td>-0.173034</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "               lag_1     lag_2     lag_3  roll_mean_20  roll_mean_10  \\\n",
       "2008-07-01  0.762137  0.816255  0.827887      0.926472      0.959856   \n",
       "2008-08-01  0.953737  0.762137  0.816255      0.918757      0.944132   \n",
       "2008-09-01  1.027884  0.953737  0.762137      0.914148      0.935922   \n",
       "2008-10-01  0.963651  1.027884  0.953737      0.901165      0.915934   \n",
       "2008-11-01  1.096952  0.963651  1.027884      0.926125      0.907970   \n",
       "\n",
       "            rolling_skewness  \n",
       "2008-07-01         -0.130309  \n",
       "2008-08-01         -0.053265  \n",
       "2008-09-01         -0.024878  \n",
       "2008-10-01         -0.022704  \n",
       "2008-11-01         -0.173034  "
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Inspect prediction matrix\n",
    "# ==============================================================================\n",
    "forecaster.create_predict_X(steps=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "a37d1e3a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2008-07-01    0.953737\n",
       "2008-08-01    1.027884\n",
       "2008-09-01    0.963651\n",
       "2008-10-01    1.096952\n",
       "2008-11-01    1.096672\n",
       "Freq: MS, Name: pred, dtype: float64"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Predict\n",
    "# ==============================================================================\n",
    "forecaster.predict(steps=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "1907e1de",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╭────────────────────────────────── InputTypeWarning ──────────────────────────────────╮</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Passing a DataFrame (either wide or long format) as `series` requires additional     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> internal transformations, which can increase computational time. It is recommended   <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> to use a dictionary of pandas Series instead. For more details, see:                 <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> https://skforecast.org/latest/user_guides/independent-multi-time-series-forecasting. <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> html#input-data                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>                                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Category : skforecast.exceptions.InputTypeWarning                                    <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Location :                                                                           <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> c:\\Users\\jaesc2\\Miniconda3\\envs\\skforecast_py12\\Lib\\site-packages\\skforecast\\utils\\u <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> tils.py:2349                                                                         <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Suppress : warnings.simplefilter('ignore', category=InputTypeWarning)                <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╰──────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[38;5;214m╭─\u001b[0m\u001b[38;5;214m─────────────────────────────────\u001b[0m\u001b[38;5;214m InputTypeWarning \u001b[0m\u001b[38;5;214m─────────────────────────────────\u001b[0m\u001b[38;5;214m─╮\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Passing a DataFrame (either wide or long format) as `series` requires additional     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m internal transformations, which can increase computational time. It is recommended   \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m to use a dictionary of pandas Series instead. For more details, see:                 \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m https://skforecast.org/latest/user_guides/independent-multi-time-series-forecasting. \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m html#input-data                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m                                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Category : skforecast.exceptions.InputTypeWarning                                    \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Location :                                                                           \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m c:\\Users\\jaesc2\\Miniconda3\\envs\\skforecast_py12\\Lib\\site-packages\\skforecast\\utils\\u \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m tils.py:2349                                                                         \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Suppress : warnings.simplefilter('ignore', category=InputTypeWarning)                \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m╰──────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <style>\n",
       "        .container-43d28dee24e34973b2ce0c8f0096fbc9 {\n",
       "            font-family: 'Arial', sans-serif;\n",
       "            font-size: 0.9em;\n",
       "            color: #333333;\n",
       "            border: 1px solid #ddd;\n",
       "            background-color: #f0f8ff;\n",
       "            padding: 5px 15px;\n",
       "            border-radius: 8px;\n",
       "            max-width: 600px;\n",
       "            #margin: auto;\n",
       "        }\n",
       "        .container-43d28dee24e34973b2ce0c8f0096fbc9 h2 {\n",
       "            font-size: 1.5em;\n",
       "            color: #222222;\n",
       "            border-bottom: 2px solid #ddd;\n",
       "            padding-bottom: 5px;\n",
       "            margin-bottom: 15px;\n",
       "            margin-top: 5px;\n",
       "        }\n",
       "        .container-43d28dee24e34973b2ce0c8f0096fbc9 details {\n",
       "            margin: 10px 0;\n",
       "        }\n",
       "        .container-43d28dee24e34973b2ce0c8f0096fbc9 summary {\n",
       "            font-weight: bold;\n",
       "            font-size: 1.1em;\n",
       "            color: #000000;\n",
       "            cursor: pointer;\n",
       "            margin-bottom: 5px;\n",
       "            background-color: #b3dbfd;\n",
       "            padding: 5px;\n",
       "            border-radius: 5px;\n",
       "        }\n",
       "        .container-43d28dee24e34973b2ce0c8f0096fbc9 summary:hover {\n",
       "            color: #000000;\n",
       "            background-color: #e0e0e0;\n",
       "        }\n",
       "        .container-43d28dee24e34973b2ce0c8f0096fbc9 ul {\n",
       "            font-family: 'Courier New', monospace;\n",
       "            list-style-type: none;\n",
       "            padding-left: 20px;\n",
       "            margin: 10px 0;\n",
       "            line-height: normal;\n",
       "        }\n",
       "        .container-43d28dee24e34973b2ce0c8f0096fbc9 li {\n",
       "            margin: 5px 0;\n",
       "            font-family: 'Courier New', monospace;\n",
       "        }\n",
       "        .container-43d28dee24e34973b2ce0c8f0096fbc9 li strong {\n",
       "            font-weight: bold;\n",
       "            color: #444444;\n",
       "        }\n",
       "        .container-43d28dee24e34973b2ce0c8f0096fbc9 li::before {\n",
       "            content: \"- \";\n",
       "            color: #666666;\n",
       "        }\n",
       "        .container-43d28dee24e34973b2ce0c8f0096fbc9 a {\n",
       "            color: #001633;\n",
       "            text-decoration: none;\n",
       "        }\n",
       "        .container-43d28dee24e34973b2ce0c8f0096fbc9 a:hover {\n",
       "            color: #359ccb; \n",
       "        }\n",
       "    </style>\n",
       "    \n",
       "        <div class=\"container-43d28dee24e34973b2ce0c8f0096fbc9\">\n",
       "            <p style=\"font-size: 1.5em; font-weight: bold; margin-block-start: 0.83em; margin-block-end: 0.83em;\">ForecasterRecursiveMultiSeries</p>\n",
       "            <details open>\n",
       "                <summary>General Information</summary>\n",
       "                <ul>\n",
       "                    <li><strong>Estimator:</strong> LGBMRegressor</li>\n",
       "                    <li><strong>Lags:</strong> [1 2 3]</li>\n",
       "                    <li><strong>Window features:</strong> ['roll_mean_20', 'roll_mean_10', 'rolling_skewness']</li>\n",
       "                    <li><strong>Window size:</strong> 20</li>\n",
       "                    <li><strong>Series encoding:</strong> ordinal</li>\n",
       "                    <li><strong>Exogenous included:</strong> False</li>\n",
       "                    <li><strong>Weight function included:</strong> False</li>\n",
       "                    <li><strong>Series weights:</strong> None</li>\n",
       "                    <li><strong>Differentiation order:</strong> None</li>\n",
       "                    <li><strong>Creation date:</strong> 2025-11-27 12:11:03</li>\n",
       "                    <li><strong>Last fit date:</strong> 2025-11-27 12:11:03</li>\n",
       "                    <li><strong>Skforecast version:</strong> 0.19.0</li>\n",
       "                    <li><strong>Python version:</strong> 3.12.11</li>\n",
       "                    <li><strong>Forecaster id:</strong> None</li>\n",
       "                </ul>\n",
       "            </details>\n",
       "            <details>\n",
       "                <summary>Exogenous Variables</summary>\n",
       "                <ul>\n",
       "                    None\n",
       "                </ul>\n",
       "            </details>\n",
       "            <details>\n",
       "                <summary>Data Transformations</summary>\n",
       "                <ul>\n",
       "                    <li><strong>Transformer for series:</strong> None</li>\n",
       "                    <li><strong>Transformer for exog:</strong> None</li>\n",
       "                </ul>\n",
       "            </details>\n",
       "            <details>\n",
       "                <summary>Training Information</summary>\n",
       "                <ul>\n",
       "                    <li><strong>Series names (levels):</strong> item_1, item_2, item_3</li>\n",
       "                    <li><strong>Training range:</strong> 'item_1': ['2012-01-01', '2015-01-01'], 'item_2': ['2012-01-01', '2015-01-01'], 'item_3': ['2012-01-01', '2015-01-01']</li>\n",
       "                    <li><strong>Training index type:</strong> DatetimeIndex</li>\n",
       "                    <li><strong>Training index frequency:</strong> <Day></li>\n",
       "                </ul>\n",
       "            </details>\n",
       "            <details>\n",
       "                <summary>Estimator Parameters</summary>\n",
       "                <ul>\n",
       "                    {'boosting_type': 'gbdt', 'class_weight': None, 'colsample_bytree': 1.0, 'importance_type': 'split', 'learning_rate': 0.1, 'max_depth': -1, 'min_child_samples': 20, 'min_child_weight': 0.001, 'min_split_gain': 0.0, 'n_estimators': 100, 'n_jobs': None, 'num_leaves': 31, 'objective': None, 'random_state': 123, 'reg_alpha': 0.0, 'reg_lambda': 0.0, 'subsample': 1.0, 'subsample_for_bin': 200000, 'subsample_freq': 0, 'verbose': -1}\n",
       "                </ul>\n",
       "            </details>\n",
       "            <details>\n",
       "                <summary>Fit Kwargs</summary>\n",
       "                <ul>\n",
       "                    {}\n",
       "                </ul>\n",
       "            </details>\n",
       "            <p>\n",
       "                <a href=\"https://skforecast.org/0.19.0/api/forecasterrecursivemultiseries.html\">&#128712 <strong>API Reference</strong></a>\n",
       "                &nbsp;&nbsp;\n",
       "                <a href=\"https://skforecast.org/0.19.0/user_guides/independent-multi-time-series-forecasting.html\">&#128462 <strong>User Guide</strong></a>\n",
       "            </p>\n",
       "        </div>\n",
       "        "
      ],
      "text/plain": [
       "============================== \n",
       "ForecasterRecursiveMultiSeries \n",
       "============================== \n",
       "Estimator: LGBMRegressor \n",
       "Lags: [1 2 3] \n",
       "Window features: ['roll_mean_20', 'roll_mean_10', 'rolling_skewness'] \n",
       "Window size: 20 \n",
       "Series encoding: ordinal \n",
       "Series names (levels): item_1, item_2, item_3 \n",
       "Exogenous included: False \n",
       "Exogenous names: None \n",
       "Transformer for series: None \n",
       "Transformer for exog: None \n",
       "Weight function included: False \n",
       "Series weights: None \n",
       "Differentiation order: None \n",
       "Training range: \n",
       "    'item_1': ['2012-01-01', '2015-01-01'], 'item_2': ['2012-01-01', '2015-01-01'],\n",
       "    'item_3': ['2012-01-01', '2015-01-01'] \n",
       "Training index type: DatetimeIndex \n",
       "Training index frequency: <Day> \n",
       "Estimator parameters: \n",
       "    {'boosting_type': 'gbdt', 'class_weight': None, 'colsample_bytree': 1.0,\n",
       "    'importance_type': 'split', 'learning_rate': 0.1, 'max_depth': -1,\n",
       "    'min_child_samples': 20, 'min_child_weight': 0.001, 'min_split_gain': 0.0,\n",
       "    'n_estimators': 100, 'n_jobs': None, 'num_leaves': 31, 'objective': None,\n",
       "    'random_state': 123, 'reg_alpha': 0.0, 'reg_lambda': 0.0, 'subsample': 1.0,\n",
       "    'subsample_for_bin': 200000, 'subsample_freq': 0, 'verbose': -1} \n",
       "fit_kwargs: {} \n",
       "Creation date: 2025-11-27 12:11:03 \n",
       "Last fit date: 2025-11-27 12:11:03 \n",
       "Skforecast version: 0.19.0 \n",
       "Python version: 3.12.11 \n",
       "Forecaster id: None "
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Forecaster with multiple window features\n",
    "# ==============================================================================\n",
    "window_features = [\n",
    "    RollingFeatures(stats=['mean', 'mean'], window_sizes=[20, 10]),\n",
    "    RollingSkewnessMultiSeries(window_sizes=10)\n",
    "]\n",
    "\n",
    "forecaster = ForecasterRecursiveMultiSeries(\n",
    "                 estimator       = LGBMRegressor(random_state=123, verbose=-1),\n",
    "                 lags            = 3,\n",
    "                 window_features = window_features\n",
    "             )\n",
    "\n",
    "forecaster.fit(series=data_multiseries)\n",
    "forecaster"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "59f7dc0e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>level</th>\n",
       "      <th>lag_1</th>\n",
       "      <th>lag_2</th>\n",
       "      <th>lag_3</th>\n",
       "      <th>roll_mean_20</th>\n",
       "      <th>roll_mean_10</th>\n",
       "      <th>rolling_skewness</th>\n",
       "      <th>_level_skforecast</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2015-01-02</th>\n",
       "      <td>item_1</td>\n",
       "      <td>10.496302</td>\n",
       "      <td>18.721223</td>\n",
       "      <td>18.857026</td>\n",
       "      <td>19.627230</td>\n",
       "      <td>18.109484</td>\n",
       "      <td>-1.596973</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-03</th>\n",
       "      <td>item_1</td>\n",
       "      <td>18.861343</td>\n",
       "      <td>10.496302</td>\n",
       "      <td>18.721223</td>\n",
       "      <td>19.512458</td>\n",
       "      <td>17.676044</td>\n",
       "      <td>-1.504973</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-04</th>\n",
       "      <td>item_1</td>\n",
       "      <td>17.778515</td>\n",
       "      <td>18.861343</td>\n",
       "      <td>10.496302</td>\n",
       "      <td>19.364411</td>\n",
       "      <td>17.349451</td>\n",
       "      <td>-1.337133</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-05</th>\n",
       "      <td>item_1</td>\n",
       "      <td>19.272862</td>\n",
       "      <td>17.778515</td>\n",
       "      <td>18.861343</td>\n",
       "      <td>19.293172</td>\n",
       "      <td>17.434766</td>\n",
       "      <td>-1.284426</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-06</th>\n",
       "      <td>item_1</td>\n",
       "      <td>20.198399</td>\n",
       "      <td>19.272862</td>\n",
       "      <td>17.778515</td>\n",
       "      <td>19.143477</td>\n",
       "      <td>17.800624</td>\n",
       "      <td>-1.469888</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "             level      lag_1      lag_2      lag_3  roll_mean_20  \\\n",
       "2015-01-02  item_1  10.496302  18.721223  18.857026     19.627230   \n",
       "2015-01-03  item_1  18.861343  10.496302  18.721223     19.512458   \n",
       "2015-01-04  item_1  17.778515  18.861343  10.496302     19.364411   \n",
       "2015-01-05  item_1  19.272862  17.778515  18.861343     19.293172   \n",
       "2015-01-06  item_1  20.198399  19.272862  17.778515     19.143477   \n",
       "\n",
       "            roll_mean_10  rolling_skewness  _level_skforecast  \n",
       "2015-01-02     18.109484         -1.596973                0.0  \n",
       "2015-01-03     17.676044         -1.504973                0.0  \n",
       "2015-01-04     17.349451         -1.337133                0.0  \n",
       "2015-01-05     17.434766         -1.284426                0.0  \n",
       "2015-01-06     17.800624         -1.469888                0.0  "
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Inspect prediction matrix for item_1\n",
    "# ==============================================================================\n",
    "forecaster.create_predict_X(steps=5).query(\"level == 'item_1'\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "cede7d6e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>level</th>\n",
       "      <th>pred</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2015-01-02</th>\n",
       "      <td>item_1</td>\n",
       "      <td>18.861343</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-02</th>\n",
       "      <td>item_2</td>\n",
       "      <td>21.561617</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-02</th>\n",
       "      <td>item_3</td>\n",
       "      <td>21.071428</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-03</th>\n",
       "      <td>item_1</td>\n",
       "      <td>17.778515</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-03</th>\n",
       "      <td>item_2</td>\n",
       "      <td>21.288322</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-03</th>\n",
       "      <td>item_3</td>\n",
       "      <td>20.891229</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-04</th>\n",
       "      <td>item_1</td>\n",
       "      <td>19.272862</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-04</th>\n",
       "      <td>item_2</td>\n",
       "      <td>20.580463</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-04</th>\n",
       "      <td>item_3</td>\n",
       "      <td>21.024649</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-05</th>\n",
       "      <td>item_1</td>\n",
       "      <td>20.198399</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-05</th>\n",
       "      <td>item_2</td>\n",
       "      <td>20.020874</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-05</th>\n",
       "      <td>item_3</td>\n",
       "      <td>21.414145</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-06</th>\n",
       "      <td>item_1</td>\n",
       "      <td>19.464618</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-06</th>\n",
       "      <td>item_2</td>\n",
       "      <td>20.100328</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2015-01-06</th>\n",
       "      <td>item_3</td>\n",
       "      <td>21.244314</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "             level       pred\n",
       "2015-01-02  item_1  18.861343\n",
       "2015-01-02  item_2  21.561617\n",
       "2015-01-02  item_3  21.071428\n",
       "2015-01-03  item_1  17.778515\n",
       "2015-01-03  item_2  21.288322\n",
       "2015-01-03  item_3  20.891229\n",
       "2015-01-04  item_1  19.272862\n",
       "2015-01-04  item_2  20.580463\n",
       "2015-01-04  item_3  21.024649\n",
       "2015-01-05  item_1  20.198399\n",
       "2015-01-05  item_2  20.020874\n",
       "2015-01-05  item_3  21.414145\n",
       "2015-01-06  item_1  19.464618\n",
       "2015-01-06  item_2  20.100328\n",
       "2015-01-06  item_3  21.244314"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Inspect prediction matrix\n",
    "# ==============================================================================\n",
    "forecaster.predict(steps=5)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "skforecast_py12",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
